package com.lx.inter.condition.generator.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.lx.common.utils.SqlClassUtil;
import com.lx.constant.consts.CommonConstant;
import com.lx.constant.consts.SqlFormatConstant;
import com.lx.constant.enums.SegmentEnum;
import com.lx.constant.execption.LambdaCheckException;
import com.lx.constant.segment.common.ConditionSegment;
import com.lx.inter.condition.generator.IGenerator;
import com.lx.wrapper.AbstractCommonConditionWrapper;
import com.lx.wrapper.AbstractWrapper;
import org.hibernate.query.Query;

/**
 * SQL条件生成器通用执行类
 *
 * @author lx
 * @create 2022/12/13 16:01
 **/
public class ConditionGeneratorHandler {

    /**
     * 简单条件生成器,仅返回format字符串
     */
    public static final IGenerator SIMPLE_CONDITION_GENERATOR = new IGenerator<ConditionSegment>() {
        @Override
        public String generatorCondition(AbstractWrapper parentWrapper, AbstractWrapper thisWrapper, String formatEl, ConditionSegment sg, Boolean isHQL) {
            return formatEl;
        }

        @Override
        public void setHibernateParam(ConditionSegment sg, Boolean isHQL, Query query) {
        }
    };

    /**
     * 默认条件生成器,必须保证【列名】存在;
     * 适用范围:
     * 1.isNull
     * 2.isNotNull
     */
    public static final IGenerator SIMPLE_NAME_CONDITION_GENERATOR = new IGenerator<ConditionSegment>() {

        @Override
        public String generatorCondition(AbstractWrapper parentWrapper, AbstractWrapper thisWrapper, String formatEl, ConditionSegment sg, Boolean isHQL) {
            String columnName = sg.getColumnNameBySegment(isHQL);
            if (columnName == null) {
                return CommonConstant.EMPTY;
            }
            return String.format(formatEl, thisWrapper.getTableAliasName(true, sg.getColumnEntityClass()) + columnName);
        }

        @Override
        public void setHibernateParam(ConditionSegment sg, Boolean isHQL, Query query) {
        }
    };

    /**
     * 默认条件生成器,必须保证【列名】和条件【值/子条件项/属性】存在;适用范围:IN 等
     */
    public static final IGenerator DEFAULT_CONDITION_GENERATOR = new IGenerator<ConditionSegment>() {
        @Override
        public String generatorCondition(AbstractWrapper parentWrapper, AbstractWrapper thisWrapper, String formatEl, ConditionSegment sg, Boolean isHQL) {
            String columnName = sg.getColumnNameBySegment(isHQL);
            if (StrUtil.isEmpty(columnName)) {
                //如列名属性无法获取
                return CommonConstant.EMPTY;
            }
            //生成拼接项 1.生成带表前缀的列名 2.生成条件数据
            String cl = thisWrapper.getTableAliasName(true, sg.getColumnEntityClass()) + columnName, cr = CommonConstant.EMPTY;

            if (sg.getChildConditionWrapper() != null) {
                //子条件项 条件拼接
                cr = String.format(SqlFormatConstant.PARENTHESES_FORMAT, sg.getChildConditionWrapper().getCompleteQL(isHQL, thisWrapper));
            } else if (ArrayUtil.isNotEmpty(sg.getColumnValue())) {
                //列值 条件拼接
                cr = sg.getHibernatePlaceholder(true);
            } else if (sg.getConditionField() != null) {
                //[其他/当前]表属性 条件拼接 注意:此处暂不支持解析特殊Hibernate写法
                cr = thisWrapper.getTableAliasName(true, sg.getConditionEntityClass()) + SqlClassUtil.findColumnNameByField(isHQL, sg.getConditionField(), true);
            }
            if (StrUtil.isEmpty(cr)) {
                //未成功生成条件项
                return CommonConstant.EMPTY;
            }
            return String.format(formatEl, cl, cr);
        }

        @Override
        public void setHibernateParam(ConditionSegment sg, Boolean isHQL, Query query) {
            if (ArrayUtil.isNotEmpty(sg.getColumnValue())) {
                //可能存在子条件语句,则不进行设值
                query.setParameterList(sg.getHibernatePlaceholder(false), sg.getColumnValue());
            }
        }
    };

    /**
     * like条件生成器
     */
    public static final IGenerator LIKE_CONDITION_GENERATOR = new IGenerator<ConditionSegment>() {

        @Override
        public String generatorCondition(AbstractWrapper parentWrapper, AbstractWrapper thisWrapper, String formatEl, ConditionSegment sg, Boolean isHQL) {
            String columnName = sg.getColumnNameBySegment(isHQL);
            if (columnName == null || ArrayUtil.isEmpty(sg.getColumnValue())) {
                return CommonConstant.EMPTY;
            }
            return String.format(formatEl, thisWrapper.getTableAliasName(true, sg.getColumnEntityClass()) + columnName, sg.getHibernatePlaceholder(true));
        }

        @Override
        public void setHibernateParam(ConditionSegment sg, Boolean isHQL, Query query) {
            if (ArrayUtil.isNotEmpty(sg.getColumnValue())) {
                //组装和拼接
                String likeValues = ArrayUtil.join(sg.getColumnValue(), CommonConstant.EMPTY);
                query.setParameter(sg.getHibernatePlaceholder(false), likeValues);
            }

        }
    };

    /**
     * OR条件生成器
     */
    public static final IGenerator OR_CONDITION_GENERATOR = new IGenerator<ConditionSegment>() {

        @Override
        public String generatorCondition(AbstractWrapper parentWrapper, AbstractWrapper thisWrapper, String formatEl, ConditionSegment sg, Boolean isHQL) {
            AbstractCommonConditionWrapper childConditionWrapper = sg.getChildConditionWrapper();
            if (sg == null || childConditionWrapper == null) {
                return formatEl;
            }
            boolean isSameEntity = thisWrapper.getEntityClass().equals(childConditionWrapper.getEntityClass());
            String cValue;
            //OR条件下,如子Wrapper和
            if (isSameEntity && StrUtil.isEmpty(childConditionWrapper.tryGetQLFragment(isHQL, SegmentEnum.COLUMN, thisWrapper))) {
                //设置别名传递
                childConditionWrapper.setTableAlias(thisWrapper.getTableAliasName(false, sg.getColumnEntityClass()));
                cValue = childConditionWrapper.tryGetQLFragment(isHQL, SegmentEnum.WHERE, thisWrapper);
            } else {
                cValue = childConditionWrapper.getCompleteQL(isHQL, thisWrapper);
            }
            return formatEl + String.format("( %s )", cValue);
        }

        @Override
        public void setHibernateParam(ConditionSegment sg, Boolean isHQL, Query query) {
        }
    };

    /**
     * exists条件生成器
     */
    public static final IGenerator EXISTS_CONDITION_GENERATOR = new IGenerator<ConditionSegment>() {

        @Override
        public String generatorCondition(AbstractWrapper parentWrapper, AbstractWrapper thisWrapper, String formatEl, ConditionSegment sg, Boolean isHQL) {
            return sg.getChildConditionWrapper() == null ? null : String.format(formatEl, sg.getChildConditionWrapper().getCompleteQL(isHQL, thisWrapper));
        }

        @Override
        public void setHibernateParam(ConditionSegment sg, Boolean isHQL, Query query) {
            //属性和值均不存在,不进行映射
        }
    };

    /**
     * between...and条件生成器
     */
    public static final IGenerator BETWEEN_AND_CONDITION_GENERATOR = new IGenerator<ConditionSegment>() {

        @Override
        public String generatorCondition(AbstractWrapper parentWrapper, AbstractWrapper thisWrapper, String formatEl, ConditionSegment sg, Boolean isHQL) {
            String columnName = sg.getColumnNameBySegment(isHQL);
            Object[] columnValue = sg.getColumnValue();

            if (columnName == null || ArrayUtil.isEmpty(columnValue)) {
                return CommonConstant.EMPTY;
            }
            if (columnValue.length < 2) {
                throw new LambdaCheckException("SQL语句中BETWEEN...AND...至少应保证两个必传参数!");
            }
            String hibernatePlaceholder = sg.getHibernatePlaceholder(true);
            return String.format(formatEl, thisWrapper.getTableAliasName(true, sg.getColumnEntityClass()) + columnName, hibernatePlaceholder + 0, hibernatePlaceholder + 1);
        }

        @Override
        public void setHibernateParam(ConditionSegment sg, Boolean isHQL, Query query) {
            String hibernatePlaceholder = sg.getHibernatePlaceholder(false);
            Object[] columnValue = sg.getColumnValue();
            query.setParameter(hibernatePlaceholder + 0, columnValue[0]);
            query.setParameter(hibernatePlaceholder + 1, columnValue[1]);
        }
    };

}
